/**
 * @file ex1.cpp
 * @author your name (you@domain.com)
 * @brief 给定一个string,将它转换为另一个string。
 * @version 0.1
 * @date 2020-12-08
 * 
 * @copyright Copyright (c) 2020
 * 
 */
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <stdexcept>
/**
 * @brief 接受一个string，如果存在转换规则，返回转换后的内容
 * 
 * @param map_file 单词转换文件
 * @param input 要转换的文本文件
 */
void word_transform(std::ifstream &map_file, std::ifstream &input)
{
    auto trans_map = buildMap(map_file); // 保存转换规则
    std::string text; // 保存输入中的每一行
    while(std::getline(input, text)) // 读取一行输入
    {
        std::istringstream stream(text); // 读取每个单词
        std::string word;
        bool firstword = true; // 控制是否打印空格
        while(stream >> word)
        {
            if(firstword)
            {
                firstword = false;
            }
            else
            {
                std::cout << " "; // 在单词间打印一个空额
            }
            // transform 返回它的第一个参数或其转换之后的形式
            std::cout << transform(word, trans_map); // 打印输出    
        }
        std::cout << std::endl; // 完成一行的转换
    }
}
/**
 * @brief 读取给定文件，建立起转换映射
 * 
 * @param map_file 
 * @return std::map<std::string, std::string> 
 */
std::map<std::string, std::string> buildMap(std::ifstream &map_file)
{
    std::map<std::string, std::string> trans_map; // 保存转换规则
    std::string key; // 要转换的单词
    std::string value; // 替换后的内容
    // 读取第一个单词存入 key 中，行中剩余内容存入 value
    while (map_file >> key && std::getline(map_file, value))
    {
        if(value.size() > 1) // 检查是否有转换规则
        {
            trans_map[key] = value.substr(1); // 跳过前导空格
            // trans_map.insert({key, value.substr(1)});
        }
        else
        {
            throw std::runtime_error("No rule for " + key);
        }
        return trans_map;
    }  
}
/**
 * @brief 如果给定string在map中，返回相应的短语；否则，返回原string
 * 
 * @param s 需要转换的 string
 * @param m 转换规则 map
 * @return const std::string& 
 */
const std::string & transform(const std::string &s, const std::map<std::string, std::string> &m)
{
    // 实际的转换工作，此部分是程序的核心
    auto map_it = m.find(s);
    // 如果单词在转换规则 map 中
    if(map_it != m.cend())
    {
        return map_it->second; // 使用替换短语
    }
    else
    {
        return s; // 否则返回原sting
    }
}